module dice.render.giza;

import dice.render.painter;
import dice.render.canvas;
import dice.render.shape;
import dice.render.structs;
import dice.render.pattern;

import std.stdio;

/** A canvas that can be drawn to using Giza */
interface GizaCanvas
{
}

/** The same as dice.render.canvas.Pixmap, but it uses Giza for painting */
class Pixmap : dice.render.canvas.Pixmap, GizaCanvas
{
	this (int w, int h)
	{
		super(w,h);
	}
	
	/+Painter painter ()
	{
		return new GizaPainter(this);
	}+/
}

/** The status of a painter */
private struct GizaStatus
{
	/* Basic settings */
	float width;
	float alpha;
	
	/* The current path */
	Path path;
	
	/* Matrix */
	Matrix matrix;
	Matrix inverseMatrix;
	
	/* Source */
	bool complexSource;
	union
	{
		Colour colour;
		Pattern pattern;
	}
	
	/* Copy */
	GizaStatus copy ()
	{
		GizaStatus s = *this;
		
		s.path = new Path(path);
		
		return s;
	}
	
	/* Initial */
	static GizaStatus initial ()
	{
		GizaStatus s;
		
		s.width = 1.0;
		s.alpha = 1.0;
		
		s.path = new Path();
		
		s.matrix = Matrix(1,0,0,1,0,0);
		s.inverseMatrix = s.matrix.inverted;
		
		s.complexSource = false;
		s.colour = Colour(0.5,0.5,0.5,0.5);
		s.pattern = null;
		
		return s;
	}
}

/** A painter implemented in pure D code */
class GizaPainter : Painter
{
	/* Canvas */
	GizaCanvas canvas;
	
	/* Constructor */
	this (GizaCanvas c)
	{
		canvas = c;
		status = [GizaStatus.initial()];
	}
	
	void destroy ()
	{
	}
	
	/* Save/restore stack */
	GizaStatus[] status;
	
	void save ()
	{
		status = status[0].copy ~ status;
	}
	
	void restore ()
	{
		status = status[1..status.length];
	}
	
	/* Width, alpha, matrix, colour, pattern, etc. */
	void width (float w)
	{
		status[0].width = w;
	}
	
	void alpha (float a)
	{
		status[0].alpha = a;
	}
	
	void matrix (Matrix m)
	{
		status[0].matrix = status[0].matrix * m;
		status[0].inverseMatrix = status[0].matrix.inverted;
	}
	
	void pattern (Pattern p)
	{
		status[0].complexSource = true;
		status[0].pattern = p;
	}
	
	void colour (Colour c)
	{
		status[0].complexSource = false;
		status[0].colour = c;
	}
	
	/* Path and tracing */
	void line (float x, float y)
	{
		status[0].path.line(x,y);
	}
	
	void move (float x, float y)
	{
		status[0].path.move(x,y);
	}
	
	void curve (float x1, float y1, float x2, float y2, float x, float y)
	{
		status[0].path.curve(x1,y1,x2,y2,x,y);
	}
	
	void close ()
	{
		status[0].path.close();
	}
	
	/* Stroke */
	void stroke ()
	{
		strokePreserve();
		status[0].path = new Path();
	}
	
	void strokePreserve ()
	{
		writefln("strokePreserve!");
	}
	
	/* Fill */
	abstract void fill ()
	{
		fillPreserve();
		status[0].path = new Path();
	}
	
	void fillPreserve ()
	{
		writefln("fillPreserve!");
	}
	
	/* Clip */
	void clip ()
	{
		clipPreserve();
	}
	
	void clipPreserve ()
	{
		writefln("clipPreserve!");
	}
	
	/* Fill All */
	void fillAll()
	{
		writefln("fillAll!");
	}
}
